/**
 * Pr�klady pou�it� t��dy UniQLBracketExpr
 * UniQLBracketExpr expr = new UniQLBracketExpr();
 * expr.setDialect(dialect);
 * expr.add(new Object[] {"1", "-", "DISC1", "/", "100"});
 * 
 * UniQLBracketExpr expr2 = new UniQLBracketExpr()
 * .add(new Object[] {"MUNIT_PRICE", "*", 
 * new UniQLBracketExpr().add(new Object[] {"1", "-", "DISC1", "/", "100"}), "+", "100"});
 *
 * @author www.smart4web.cz
 */
package cz.acies.uniql.sql.functions;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;


import cz.acies.uniql.dialect.Dialect;
import cz.acies.uniql.sql.UniQLExpr;
import cz.acies.uniql.sql.element.UniQLColumn;
import cz.acies.uniql.sql.element.UniQLValue;
import cz.acies.utils.StringUtils;

public class UniQLBracketExpr extends UniQLExpr
{
	private static final long serialVersionUID = 8376178876005294533L;
	
	private static final int PLUS 	= 0; 	// "+"
	private static final int MINUS 	= 1; 	// "-"
	private static final int MULTI 	= 2; 	// "*"
	private static final int DIV 	= 3; 	// "/"
	
	private static LinkedHashMap<String, Integer> operators = new LinkedHashMap<String, Integer>();
	static {
		operators.put("+", new Integer(PLUS));
		operators.put("-", new Integer(MINUS));
		operators.put("*", new Integer(MULTI));
		operators.put("/", new Integer(DIV));
	}
	private static List<String> opidx = new ArrayList<String>(operators.keySet());
	
	List<Object> params = new ArrayList<Object>();
	
	public UniQLBracketExpr() {}
	
	public UniQLBracketExpr(Object[] args) {
		this();
		this.add(args);
	}
	
	/* (non-Javadoc)
	 * @see cz.acies.uniql.sql.UniQLExpr#translate()
	 */
	@Override
	public String translate() throws Exception {
		StringBuilder sb = new StringBuilder();
		Dialect dialect = this.getDialect();
		for (Iterator<Object> iterator = params.iterator(); iterator.hasNext();) {
			Object obj = iterator.next();
			if (obj instanceof Integer) {
				sb.append(" "+opidx.get(((Integer)obj).intValue())+" ");
			} else if (obj instanceof UniQLExpr) {
				UniQLExpr expr = (UniQLExpr)obj;
				expr.setUniQLProperties(this);
				//expr.setDialect(dialect);
				//System.out.println(expr.getName()+" "+expr.getDialect());
				sb.append(expr.translate());
			} else {
				String s = obj.toString();
				if (s.equalsIgnoreCase("AND") || s.equalsIgnoreCase("OR")) {
					sb.append(" "+s.toUpperCase()+" ");
				} else {
					sb.append(s);
				}
			}
		}
		return "("+sb.toString()+")";
	}	
	
	public UniQLBracketExpr add(Object[] args) {
		for (Object obj : args) {
			if (obj instanceof String) {
				String s = ((String)obj).trim();
				if (operators.containsKey(((String) obj).trim())) {
					params.add(operators.get(s));
				} else if (s.equalsIgnoreCase("AND") || s.equalsIgnoreCase("OR")) {
					params.add(s.toUpperCase());
				} else {
					params.add(makeExpr(obj));
				}
			} else {
				params.add(makeExpr(obj));
			}
		}
		return this;
	}

	private UniQLExpr makeExpr(Object obj) {
		if (obj instanceof String) {
			String s = ((String)obj).trim();
			if (operators.containsKey(((String) obj).trim())) {
				//params.add(operators.get(s));
				return null;
			} else {
				UniQLExpr expr = null;
				if (s.matches(StringUtils.NUMERIC_PATTERN) ||
					s.matches(StringUtils.INTEGER_PATTERN) ||
					s.matches("\\'.*\\'")) {
					
					expr = new UniQLValue(obj.toString());						
				} else if (s.matches("\\w*?\\.?\\w+")) {
					expr = new UniQLColumn(obj.toString());	
				} else {
					expr = new UniQLValue(obj.toString());						
				}
				expr.setDialect(getDialect());
				expr.setAliasMap(getAliasMap());
				return expr; 
			}
		} else if (obj instanceof UniQLExpr) {
			((UniQLExpr)obj).setDialect(getDialect());
			((UniQLExpr)obj).setAliasMap(getAliasMap());
			return ((UniQLExpr)obj);
		}
		return null;
	}

	public String toString() {
		return "" + this.getClass().getSimpleName() + 
			" ( " + params + " )";
	}
}
